/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lanSimulation.tests;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import junit.extensions.ExceptionTestCase;
import junit.framework.TestCase;
import junit.framework.TestResult;
import lanSimulation.LogManager;
import lanSimulation.Network;
import lanSimulation.internals.AsciiDocument;
import lanSimulation.internals.PSDocument;

/**
 *
 * @author farooq
 */
public class NetworkTest extends TestCase {

        private void closeFile(FileInputStream file){
            if(file != null){
                try{
                    file.close();
                }
                catch(IOException ex){
                    
                }
            }
        }

    	private boolean compareFiles(String filename1, String filename2) {
		FileInputStream f1 = null, f2 = null;
		int b1 = 0, b2 = 0;
		
		try {

                        f1 = new FileInputStream(filename1);
			f2 = new FileInputStream(filename2);

			if (f1.available() != f2.available()) {
				return false;
    			} // length of files is different
			while ((b1 != -1) & (b2 != -1)) {
				b1 = f1.read();
				b2 = f2.read();
				if (b1 != b2) {
					return false;
				} // discovered one diferring character
			}

			if ((b1 == -1) & (b2 == -1)) {
				return true; // reached both end of files
			} else {
				return false; // one end of file not reached
			}
		}
                catch(FileNotFoundException ex){
                    return false;
                }
                catch (IOException exc) {
                    return false; // read error, assume one file corrupted
		}
                finally {
			closeFile(f1);
                        closeFile(f2);
		}
	}

	
	public void testDefaultNetworkToString() {
		StringWriter report = new StringWriter(500);
                Network network = Network.DefaultExample(new LogManager(report));

		assertTrue("isInitialized ", network.isInitialized());
		assertTrue("consistentNetwork ", network.consistentNetwork());
		assertEquals(
				"DefaultNetwork.toString()",
				network.toString(),
				"Workstation Filip [Workstation] -> Node n1 [Node] -> Workstation Hans [Workstation] -> Printer Andy [Printer] ->  ... ");
	}

        public void testHasWorkstations(){
            StringWriter report = new StringWriter(100);
            Network network = Network.DefaultExample(new LogManager(report));

            assertTrue(network.hasWorkstation("Filip"));
            assertFalse(network.hasWorkstation("n1"));

        }

	public void testWorkstationPrintsDocument() {
		StringWriter report = new StringWriter(500);
                Network network = Network.DefaultExample(new LogManager(report));

		assertTrue("PrintSuccess ", network.requestWorkstationPrintsDocument(
				"Filip", new AsciiDocument("Hello World"), "Andy"));
		assertFalse("PrintFailure (UnkownPrinter) ", network
				.requestWorkstationPrintsDocument("Filip", new AsciiDocument("Hello World"),
						"UnknownPrinter"));
		assertFalse("PrintFailure (print on Workstation) ", network
				.requestWorkstationPrintsDocument("Filip", new AsciiDocument("Hello World"),
						"Hans"));
		assertFalse("PrintFailure (print on Node) ", network
				.requestWorkstationPrintsDocument("Filip", new AsciiDocument("Hello World"), "n1"));
		assertTrue("PrintSuccess Postscript", network
				.requestWorkstationPrintsDocument("Filip",
						new PSDocument("!PS Hello World in postscript"), "Andy"));
		assertFalse("PrintFailure Postscript", network
				.requestWorkstationPrintsDocument("Filip",
						new PSDocument("!PS Hello World in postscript"), "Hans"));
	}

	public void testBroadcast() {
		StringWriter report = new StringWriter(500);
                Network network = Network.DefaultExample(new LogManager(report));

		assertTrue("Broadcast ", network.requestBroadcast());
	}

	/**
	 * Test whether output routines work as expected. This is done by comparing
	 * generating output on a file "useOutput.txt" and comparing it to a file
	 * "expectedOutput.txt". On a first run this test might break because the
	 * file "expectedOutput.txt" does not exist. Then just run the test, verify
	 * manually whether "useOutput.txt" conforms to the expected output and if
	 * it does rename "useOutput.txt" in "expectedOutput.txt". From then on the
	 * tests should work as expected.
	 */
	public void testOutput() {
		StringWriter report = new StringWriter(500);
                Network network = Network.DefaultExample(new LogManager(report));

		String generateOutputFName = "useOutput.txt", expectedOutputFName = "expectedOutput.txt";
		FileWriter generateOutput;
		StringBuffer buf = new StringBuffer(500);
		

		try {
			generateOutput = new FileWriter(generateOutputFName);
		} catch (IOException f2exc) {
			assertTrue("Could not create '" + generateOutputFName + "'", false);
			return;
		}

		try {
			buf.append("---------------------------------ASCII------------------------------------------\n");
			network.printOn(buf);
			buf.append("\n\n---------------------------------HTML------------------------------------------\n");
			network.printHTMLOn(buf);
			buf.append("\n\n---------------------------------XML------------------------------------------\n");
			network.printXMLOn(buf);
			generateOutput.write(buf.toString());
			report.write("\n\n---------------------------------SCENARIO: Print Success --------------------------\n");
			network.requestWorkstationPrintsDocument("Filip", new AsciiDocument("Hello World"),
					"Andy");
			report.write("\n\n---------------------------------SCENARIO: PrintFailure (UnkownPrinter) ------------\n");
			network.requestWorkstationPrintsDocument("Filip", new AsciiDocument("Hello World"),
					"UnknownPrinter");
			report.write("\n\n---------------------------------SCENARIO: PrintFailure (print on Workstation) -----\n");
			network.requestWorkstationPrintsDocument("Filip",  new AsciiDocument("Hello World"),
					"Hans");
			report.write("\n\n---------------------------------SCENARIO: PrintFailure (print on Node) -----\n");
			network.requestWorkstationPrintsDocument("Filip",  new AsciiDocument("Hello World"),
					"n1");
			report.write("\n\n---------------------------------SCENARIO: Print Success Postscript-----------------\n");
			network.requestWorkstationPrintsDocument("Filip",
					new PSDocument("!PS Hello World in postscript"), "Andy");
			report.write("\n\n---------------------------------SCENARIO: Print Failure Postscript-----------------\n");
			network.requestWorkstationPrintsDocument("Filip",
					new PSDocument("!PS Hello World in postscript"), "Hans");
			report.write("\n\n---------------------------------SCENARIO: Broadcast Success -----------------\n");
			network.requestBroadcast();
			generateOutput.write(report.toString());
		} catch (IOException exc) {
		} finally {
			try {
				generateOutput.close();
			} catch (IOException exc) {
			}
		}
		assertTrue("Generated output is not as expected ", compareFiles(
				generateOutputFName, expectedOutputFName));
	}

	static public class PreconditionViolationTestCase extends ExceptionTestCase {
		@SuppressWarnings("unchecked")
		public PreconditionViolationTestCase(String name, Class exception) {
			super(name, exception);
		}

		public void test() {
			StringWriter report = new StringWriter(100);
                        Network network = Network.DefaultExample(new LogManager(report));
			network.requestWorkstationPrintsDocument("UnknownWorkstation",
			new AsciiDocument("does not matter"), "does not matter");
		}
	}

	public void testPreconditionViolation() {
		PreconditionViolationTestCase test = new PreconditionViolationTestCase(
				"test", AssertionError.class);
		TestResult result = test.run();
		assertEquals(1, result.runCount());
		assertEquals(1, result.errorCount());
	}

}
